home *** CD-ROM | disk | FTP | other *** search
/ AppleScript - The Beta Release / AppleScript - The Beta Release.iso / Documentation / develop / Better Apple Event Coding / Code Samples / TESample.cp < prev    next >
Encoding:
Text File  |  1992-10-16  |  19.3 KB  |  845 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------------------
  2.  
  3.     Program:    CPlusTESample 2.0AE
  4.     File:        TESample.cp
  5.     Uses:       TEDocument.h
  6.                 TESample.h
  7.  
  8.     by Andrew Shebanow
  9.     of Apple Macintosh Developer Technical Support
  10.     with modifications by Eric Berdahl
  11.  
  12.     Copyright © 1989-1990 Apple Computer, Inc.
  13.     Copyright © 1992 Eric Berdahl
  14.     All rights reserved.
  15.  
  16. ------------------------------------------------------------------------------------------*/
  17.  
  18. #ifndef __TYPES__
  19. #include <Types.h>
  20. #endif
  21. #ifndef __QUICKDRAW__
  22. #include <QuickDraw.h>
  23. #endif
  24. #ifndef __FONTS__
  25. #include <Fonts.h>
  26. #endif
  27. #ifndef __EVENTS__
  28. #include <Events.h>
  29. #endif
  30. #ifndef __CONTROLS__
  31. #include <Controls.h>
  32. #endif
  33. #ifndef __WINDOWS__
  34. #include <Windows.h>
  35. #endif
  36. #ifndef __MENUS__
  37. #include <Menus.h>
  38. #endif
  39. #ifndef __TEXTEDIT__
  40. #include <TextEdit.h>
  41. #endif
  42. #ifndef __DIALOGS__
  43. #include <Dialogs.h>
  44. #endif
  45. #ifndef __DESK__
  46. #include <Desk.h>
  47. #endif
  48. #ifndef __SCRAP__
  49. #include <Scrap.h>
  50. #endif
  51. #ifndef __TOOLUTILS__
  52. #include <ToolUtils.h>
  53. #endif
  54. #ifndef __MEMORY__
  55. #include <Memory.h>
  56. #endif
  57. #ifndef __SEGLOAD__
  58. #include <SegLoad.h>
  59. #endif
  60. #ifndef __FILES__
  61. #include <Files.h>
  62. #endif
  63. #ifndef __OSUTILS__
  64. #include <OSUtils.h>
  65. #endif
  66. #ifndef __TRAPS__
  67. #include <Traps.h>
  68. #endif
  69. #ifndef __PACKAGES__
  70. #include <Packages.h>
  71. #endif
  72. #ifndef __ERRORS__
  73. #include <Errors.h>
  74. #endif
  75.  
  76. // our class definitions
  77. #ifndef __AEOBJECTS__
  78. #include "AEObjects.h"
  79. #endif
  80. #ifndef __AEREGISTRY__
  81. #include "AERegistry.h"
  82. #endif
  83. #ifndef __TEDOCUMENT__
  84. #include "TEDocument.h"
  85. #endif
  86. #ifndef __TESAMPLE__
  87. #include "TESample.h"
  88. #endif
  89.  
  90. // ExtremeNeg and ExtremePos are used to set up wide open rectangles and regions.
  91. const short kExtremeNeg = -32768;
  92. const short kExtremePos = 32767 - 1; // required to address an old region bug
  93.  
  94. // kMaxOpenDocuments is used to determine whether a new document can be opened
  95. // or created. We keep track of the number of open documents, and disable the
  96. // menu items that create a new document when the maximum is reached. If the
  97. // number of documents falls below the maximum, the items are enabled again.
  98. const short    kMaxOpenDocuments = 4;
  99.  
  100. const OSType kCreatorType = 'MOOT';
  101.  
  102. // Define max and min macros for efficiency.
  103. #define max(a,b)        ((a) > (b) ? (a) : (b))
  104. #define min(a,b)        ((a) < (b) ? (a) : (b))
  105.  
  106. // main is the entrypoint to the program
  107. int main()
  108. {
  109.     // Create our application object. This MUST be the FIRST thing
  110.     // done in main(), since it initializes the Toolbox for us.
  111.     // And since we really don’t need more than one, and since
  112.     // it’s faster and less heap-fragmenting to allocate it on the
  113.     // stack, we do.
  114.     TESample    theApp;
  115.  
  116.     theApp.ProcessArgs();
  117.  
  118.     // Start our main event loop running. This won't return until user quits
  119.     theApp.EventLoop();
  120.  
  121.     // We always return a value, like good little ANSI worshippers,
  122.     // so that the compiler won't complain
  123.     return 0;
  124. }
  125.  
  126. // the constructor for our class, called automatically when we create
  127. // an instance of this class. In this particular case, we only want
  128. // one instance since the constructor does all the menu setups and
  129. // creates our (untitled) document.
  130. // Note that we call our base TApplication constructor, passing it
  131. // our creator signature constant.
  132. TESample::TESample() : TApplication(kCreatorType)
  133. {
  134.     Handle    menuBar;
  135.  
  136.     // initialize AppleEvent code
  137.     MAppleObject::InitAppleObject();
  138.  
  139.     // read menus into menu bar
  140.     menuBar = GetNewMBar(rMenuBar);
  141.     // install menus
  142.     SetMenuBar(menuBar);
  143.     DisposHandle(menuBar);
  144.     // add DA names to Apple menu
  145.     AddResMenu(GetMHandle(mApple), 'DRVR');
  146.     // add font names to Font menu
  147.     AddResMenu(GetMHandle(mFont), 'FONT');
  148.     DrawMenuBar();
  149.  
  150.     // create empty mouse region
  151.     fMouseRgn = NewRgn();
  152.     // make sure we have a valid cursor region
  153.     AdjustCursor();
  154.  
  155.     MAppleObject::SetDefaultAppleObject(this);
  156. }
  157.  
  158. TESample* TESample::GetTEApplication()
  159. {
  160.     return (TESample*) TApplication::GetApplication();
  161. }
  162.  
  163. // Tell TApplication class how much heap we need
  164. long TESample::HeapNeeded()
  165. {
  166.     return (kMinSize * 1024);
  167. }
  168.  
  169. // Calculate a sleep value for WaitNextEvent. This takes into account the things
  170. // that DoIdle does with idle time.
  171.  
  172. unsigned long TESample::SleepVal()
  173. {
  174.     unsigned long sleep;
  175.  
  176.     sleep = kMaxSleepTime;                // default value for sleep
  177.     // if we aren't in background, let document tell us how long to sleep
  178.     if ((!fInBackground) && (fCurDoc != nil))
  179.       sleep = min(sleep,fCurDoc->CalcIdle());
  180.     return sleep;
  181. }
  182.  
  183. // This is called whenever we get a null event et al.
  184. // It takes care of necessary periodic actions. For this program,
  185. // it calls TEIdle.
  186.  
  187. void TESample::DoIdle()
  188. {
  189.     TEDocument* fTECurDoc = (TEDocument*) fCurDoc;
  190.  
  191.     if (fTECurDoc != nil)
  192.       fTECurDoc->DoIdle();
  193. } // DoIdle
  194.  
  195. // Change the cursor's shape, depending on its position. This also calculates a
  196. // region that includes the cursor for WaitNextEvent.
  197.  
  198. void TESample::AdjustCursor()
  199. {
  200.     TEDocument* fTECurDoc = (TEDocument*) fCurDoc;
  201.  
  202.     // notice that we don't change cursor if front window isn't ours
  203.     if ( (!fInBackground) && (fTECurDoc != nil) )
  204.       {
  205.         RgnHandle    arrowRgn;
  206.         RgnHandle    iBeamRgn;
  207.         Point        mouse;
  208.  
  209.         // get mouse location and convert to global coordinates
  210.         GetMouse(&mouse);
  211.         LocalToGlobal(&mouse);
  212.  
  213.         // calculate regions for different cursor shapes
  214.         arrowRgn = NewRgn();
  215.         iBeamRgn = NewRgn();
  216.         // start arrowRgn wide open
  217.         SetRectRgn(arrowRgn, kExtremeNeg, kExtremeNeg, kExtremePos, kExtremePos);
  218.         // calculate iBeamRgn
  219.         fTECurDoc->GetVisTERgn(iBeamRgn);
  220.         // subtract iBeamRgn from arrowRgn
  221.         DiffRgn(arrowRgn, iBeamRgn, arrowRgn);
  222.  
  223.         // change the cursor and the region parameter
  224.         if (PtInRgn(mouse, iBeamRgn))
  225.           {
  226.             SetCursor(*GetCursor(iBeamCursor));
  227.             CopyRgn(iBeamRgn, fMouseRgn);
  228.           }
  229.         else
  230.           {
  231.             SetCursor(&qd.arrow);
  232.             CopyRgn(arrowRgn, fMouseRgn);
  233.           }
  234.         // get rid of regions we don't need anymore
  235.         DisposeRgn(arrowRgn);
  236.         DisposeRgn(iBeamRgn);
  237.       }
  238. } // AdjustCursor
  239.  
  240. // Enable and disable menus based on the current state. The
  241. // user can only select enabled menu items. We set up all the
  242. // menu items before calling MenuSelect or MenuKey, since
  243. // these are the only times that a menu item can be selected.
  244. // Note that MenuSelect is also the only time the user will
  245. // see menu items. This approach to deciding what enable/
  246. // disable state a menu item has the advantage of
  247. // concentrating all the decision-making in one routine, as
  248. // opposed to being spread throughout the application. Other
  249. // application designs may take a different approach that may
  250. // or may not be as valid.
  251.  
  252. void TESample::AdjustMenus()
  253. {
  254.     WindowPtr    frontmost;
  255.     MenuHandle    fileMenu, editMenu;
  256.     long        offset;
  257.     Boolean        undo;
  258.     Boolean        cutCopyClear;
  259.     Boolean        paste;
  260.     Boolean        save, saveAs;
  261.     Boolean        selectAll;
  262.     TEDocument* fTECurDoc = (TEDocument*) fCurDoc;
  263.  
  264.     frontmost = FrontWindow();
  265.  
  266.     fileMenu = GetMHandle(mFile);
  267.     if (fDocList->NumDocs() < kMaxOpenDocuments)
  268.       {
  269.         // New & Open are enabled when we can open more documents
  270.         EnableItem(fileMenu, iNew);
  271.         EnableItem(fileMenu, iOpen);
  272.       }
  273.     else
  274.       {
  275.         DisableItem(fileMenu, iNew);
  276.         DisableItem(fileMenu, iOpen);
  277.       }
  278.     if (frontmost != (WindowPtr) nil)    // Close is enabled when there is a window to close
  279.       EnableItem(fileMenu, iClose);
  280.     else DisableItem(fileMenu, iClose);
  281.  
  282.     editMenu = GetMHandle(mEdit);
  283.     undo = false;
  284.     cutCopyClear = false;
  285.     paste = false;
  286.     save = saveAs = false;
  287.     selectAll = false;
  288.     if (frontmost != nil)
  289.       {
  290.         selectAll = true;
  291.         if (fCurDoc == nil)
  292.           {
  293.             undo = true;                // all editing is enabled for DA windows
  294.             cutCopyClear = true;
  295.             paste = true;
  296.           }
  297.         else
  298.           {
  299.             // Cut, Copy, and Clear is enabled for app. windows with selections
  300.             if ( fTECurDoc->HaveSelection() )
  301.               cutCopyClear = true;
  302.             // If we have any TEXT in the scrap, enable paste
  303.             if ( GetScrap(nil, 'TEXT', &offset) )
  304.                 paste = true;
  305.             // enable save if we are dirty
  306.             save = fCurDoc->CanSave();
  307.             saveAs = fCurDoc->CanSaveAs();
  308.           }
  309.       }
  310.     if (save)
  311.       EnableItem(fileMenu, iSave);
  312.     else DisableItem(fileMenu, iSave);
  313.     if (saveAs)
  314.       EnableItem(fileMenu, iSaveAs);
  315.     else DisableItem(fileMenu, iSaveAs);
  316.  
  317.     if (undo)
  318.       EnableItem(editMenu, iUndo);
  319.     else DisableItem(editMenu, iUndo);
  320.     if ( cutCopyClear )
  321.       {
  322.         EnableItem(editMenu, iCut);
  323.         EnableItem(editMenu, iCopy);
  324.         EnableItem(editMenu, iClear);
  325.       }
  326.     else
  327.       {
  328.         DisableItem(editMenu, iCut);
  329.         DisableItem(editMenu, iCopy);
  330.         DisableItem(editMenu, iClear);
  331.       }
  332.     if (paste)
  333.       EnableItem(editMenu, iPaste);
  334.     else DisableItem(editMenu, iPaste);
  335.     if (selectAll)
  336.       EnableItem(editMenu, iSelectAll);
  337.     else DisableItem(editMenu, iSelectAll);
  338.  
  339.     MenuHandle    fontMenu, fontSizeMenu, styleMenu;
  340.     fontMenu = GetMHandle(mFont);
  341.     fontSizeMenu = GetMHandle(mFontSize);
  342.     styleMenu = GetMHandle(mStyle);
  343.     if (frontmost == (WindowPtr) nil)    // the “font” menus are disabled if there is no doc
  344.       {
  345.         DisableItem(fontMenu, 0);
  346.         DisableItem(fontSizeMenu, 0);
  347.         DisableItem(styleMenu, 0);
  348.       }
  349.     else
  350.       {
  351.         EnableItem(fontMenu, 0);
  352.         EnableItem(fontSizeMenu, 0);
  353.         EnableItem(styleMenu, 0);
  354.  
  355.         short    fontSize = fTECurDoc->GetSelectionFontSize();
  356.         CheckItem(fontSizeMenu, i9Point, fontSize == 9);
  357.         CheckItem(fontSizeMenu, i10Point, fontSize == 10);
  358.         CheckItem(fontSizeMenu, i12Point, fontSize == 12);
  359.         CheckItem(fontSizeMenu, i14Point, fontSize == 14);
  360.         CheckItem(fontSizeMenu, i18Point, fontSize == 18);
  361.         CheckItem(fontSizeMenu, i24Point, fontSize == 24);
  362.  
  363.         short    fontID = fTECurDoc->GetSelectionFont();
  364.         short    nFonts = CountMItems(fontMenu);
  365.         short    i;
  366.         for (i = 1; i <= nFonts; i++)
  367.             CheckItem(fontMenu, i, false);
  368.         for (i = 1; i <= nFonts; i++)
  369.         {
  370.             Str255    fontName;
  371.             short    aFontID;
  372.             GetItem(fontMenu, i, fontName);
  373.             GetFNum(fontName, &aFontID);
  374.             if (aFontID == fontID)
  375.             {
  376.                 CheckItem(fontMenu, i, true);
  377.                 break;
  378.             }
  379.         }
  380.  
  381.         CheckItem(styleMenu, iPlain, fTECurDoc->SelectionIsPlain());
  382.         CheckItem(styleMenu, iBold, fTECurDoc->SelectionIsBold());
  383.         CheckItem(styleMenu, iItalic, fTECurDoc->SelectionIsItalic());
  384.         CheckItem(styleMenu, iUnderline, fTECurDoc->SelectionIsUnderline());
  385.         CheckItem(styleMenu, iOutline, fTECurDoc->SelectionIsOutline());
  386.         CheckItem(styleMenu, iShadow, fTECurDoc->SelectionIsShadow());
  387.       }
  388.  
  389. } // AdjustMenus
  390.  
  391.  
  392. // This is called when an item is chosen from the menu bar (after calling
  393. // MenuSelect or MenuKey). It does the right thing for each command.
  394.  
  395. void TESample::DoMenuCommand(short menuID, short menuItem)
  396. {
  397.     short        itemHit;
  398.     short        fontSize;
  399.     Str255        fontName;
  400.     Str255        daName;
  401.     short        daRefNum;
  402.     WindowPtr    window;
  403.     TEDocument* fTECurDoc = (TEDocument*) fCurDoc;
  404.  
  405.     window = FrontWindow();
  406.     switch ( menuID )
  407.       {
  408.         case mApple:
  409.             switch ( menuItem )
  410.               {
  411.                 case iAbout:        // bring up alert for About
  412.                     itemHit = Alert(rAboutAlert, nil);
  413.                     break;
  414.                 default:            // all non-About items in this menu are DAs et al
  415.                     GetItem(GetMHandle(mApple), menuItem, daName);
  416.                     daRefNum = OpenDeskAcc(daName);
  417.                     break;
  418.               }
  419.             break;
  420.         case mFile:
  421.             switch ( menuItem )
  422.               {
  423.                 case iNew:
  424.                     DoNew();
  425.                     break;
  426.                 case iOpen:
  427.                     DoOpen();
  428.                     break;
  429.                 case iClose:
  430.                     if (fTECurDoc != nil)
  431.                       {
  432.                         // only close the document if the user doesn't cancel
  433.                         if (fTECurDoc->DoClose(true, yesResult, false) != cancelResult)
  434.                           {
  435.                             fDocList->RemoveDoc(fTECurDoc);
  436.                             delete fTECurDoc;
  437.                           }
  438.                       }
  439.                     else CloseDeskAcc(((WindowPeek) fWhichWindow)->windowKind);
  440.                     // make sure our current document/window references are valid
  441.                     fWhichWindow = FrontWindow();
  442.                     if (fWhichWindow != nil)
  443.                       {
  444.                         fCurDoc = fDocList->FindDoc(fWhichWindow);
  445.                         SetPort(fWhichWindow);
  446.                       }
  447.                     else fCurDoc = nil;
  448.                     break;
  449.                 case iSave:
  450.                     if (fTECurDoc != nil)
  451.                       fTECurDoc->DoSave();
  452.                     break;
  453.                 case iSaveAs:
  454.                     if (fTECurDoc != nil)
  455.                       fTECurDoc->DoSaveAs();
  456.                     break;
  457.                 case iQuit:
  458.                     DoQuit(true, yesResult);
  459.                     break;
  460.               }
  461.             break;
  462.         case mEdit:                    // call SystemEdit for DA editing & MultiFinder
  463.             if (!SystemEdit(menuItem-1))
  464.               {
  465.                 switch (menuItem)
  466.                   {
  467.                     case iCut:
  468.                         fTECurDoc->DoCut();
  469.                         break;
  470.                     case iCopy:
  471.                         fTECurDoc->DoCopy();
  472.                         break;
  473.                     case iPaste:
  474.                         fTECurDoc->DoPaste();
  475.                         break;
  476.                     case iClear:
  477.                         fTECurDoc->DoClear();
  478.                         break;
  479.                     case iSelectAll:
  480.                         fTECurDoc->DoSelectAll();
  481.                         break;
  482.                    }
  483.               }
  484.             break;
  485.         case mFont:
  486.             GetItem(GetMHandle(mFont), menuItem, fontName);
  487.             fTECurDoc->SetFontName(fontName);
  488.             break;
  489.         case mFontSize:
  490.             switch (menuItem)
  491.               {
  492.                 case i9Point:
  493.                     fontSize = 9;
  494.                     break;
  495.                 case i10Point:
  496.                     fontSize = 10;
  497.                     break;
  498.                 case i12Point:
  499.                     fontSize = 12;
  500.                     break;
  501.                 case i14Point:
  502.                     fontSize = 14;
  503.                     break;
  504.                 case i18Point:
  505.                     fontSize = 18;
  506.                     break;
  507.                 case i24Point:
  508.                     fontSize = 24;
  509.                     break;
  510.               }
  511.             fTECurDoc->SetFontSize(fontSize);
  512.             break;
  513.         case mStyle:
  514.             switch (menuItem)
  515.               {
  516.                 case iPlain:
  517.                     fTECurDoc->SetPlain();
  518.                     break;
  519.                 case iBold:
  520.                     fTECurDoc->SetBold(!fTECurDoc->SelectionIsBold());
  521.                     break;
  522.                 case iItalic:
  523.                     fTECurDoc->SetItalic(!fTECurDoc->SelectionIsItalic());
  524.                     break;
  525.                 case iUnderline:
  526.                     fTECurDoc->SetUnderline(!fTECurDoc->SelectionIsUnderline());
  527.                     break;
  528.                 case iOutline:
  529.                     fTECurDoc->SetOutline(!fTECurDoc->SelectionIsOutline());
  530.                     break;
  531.                 case iShadow:
  532.                     fTECurDoc->SetShadow(!fTECurDoc->SelectionIsShadow());
  533.                     break;
  534.               }
  535.             break;
  536.       }
  537.     HiliteMenu(0);                    // unhighlight what MenuSelect (or MenuKey) hilited
  538. } // DoMenuCommand
  539.  
  540. // Create a new document and window.
  541.  
  542. void TESample::DoNew()
  543. {
  544.     TEDocument* tDoc;
  545.  
  546.     tDoc = new TEDocument(rDocWindow);
  547.     FailNIL(tDoc);
  548.  
  549.     TRY
  550.       {
  551.         tDoc->OpenNewDoc();
  552.         fDocList->AddDoc(tDoc);
  553.       }
  554.     RECOVER
  555.       {
  556.         delete tDoc;
  557.       }
  558.     ENDTRY
  559. } // DoNew
  560.  
  561. void TESample::OpenADoc(short vRefNum, long dirID, StringPtr fName, OSType fType)
  562. {
  563.     if (fType != kTEFileType)
  564.       Failure(eBadFileType,kTEDocErrStrings);
  565.  
  566.     TEDocument* tDoc = new TEDocument(rDocWindow);
  567.     FailNIL(tDoc);
  568.  
  569.     TRY
  570.       {
  571.         FSSpec fileSpec;
  572.  
  573.         fileSpec.vRefNum = vRefNum;
  574.         fileSpec.parID = dirID;
  575.         CopyPString(fileSpec.name, fName);
  576.  
  577.         tDoc->OpenOldDoc(fileSpec,false);
  578.         fDocList->AddDoc(tDoc);
  579.       }
  580.     RECOVER
  581.       {
  582.         delete tDoc;
  583.       }
  584.     ENDTRY
  585. }
  586.  
  587. void TESample::DoOpen()
  588. {
  589.     Point where;
  590.     Str255 prompt;
  591.     SFTypeList typeList;
  592.     SFReply reply;
  593.     short vRefNum;
  594.     long dirID;
  595.  
  596.     SetPt(&where,100,100);
  597.     prompt[0] = '\0';
  598.     typeList[0] = kTEFileType;
  599.     SFGetFile(where,prompt,(FileFilterProcPtr) nil,
  600.               1,typeList,(DlgHookProcPtr) nil,&reply);
  601.     if (reply.good == false)
  602.       return;
  603.  
  604.     WDToDirID(reply.vRefNum,vRefNum,dirID);
  605.     OpenADoc(vRefNum,dirID,reply.fName, kTEFileType);
  606. }
  607.  
  608.  
  609. DescType TESample::GetAppleClass() const
  610. {
  611.     return typeNull;
  612. }
  613.  
  614.  
  615. long TESample::CountContainedObjects(DescType ofType)
  616. {
  617.     long    result = 0;
  618.  
  619.     switch (ofType)
  620.     {
  621.     case cWindow:
  622.         result = this->DocList()->NumDocs();
  623.         break;
  624.     }
  625.  
  626.     // now, add the number of objects contained by parents
  627.     result += MAppleObject::CountContainedObjects(ofType);
  628.  
  629.     return result;
  630. }
  631.  
  632.  
  633. void TESample::DoAppleEvent(const AppleEvent& message, AppleEvent& reply, long refCon)
  634. {
  635.     switch (refCon)
  636.     {
  637.     case cFinderNew:
  638.         this->DoFinderNew(message, reply);
  639.         break;
  640.     case cFinderOpen:
  641.         this->DoFinderOpen(message, reply);
  642.         break;
  643.     case cFinderPrint:
  644.         this->DoFinderPrint(message, reply);
  645.         break;
  646.     case cFinderQuit:
  647.         this->DoFinderQuit(message, reply);
  648.         break;
  649.     case cNewElement:
  650.         this->DoAppleNewElement(message, reply);
  651.         break;
  652.     default:
  653.         MAppleObject::DoAppleEvent(message, reply, refCon);
  654.         break;
  655.     }
  656. }
  657.  
  658.  
  659. MAppleObject* TESample::GetContainedObject(DescType desiredType, DescType keyForm,
  660.                                            const AEDesc& keyData, Boolean& needDisposal)
  661. {
  662.     MAppleObject*    result = nil;
  663.  
  664.     switch (desiredType)
  665.     {
  666.     case cWindow:
  667.         result = this->GetWindowObject(keyForm, keyData);
  668.         needDisposal = false;
  669.         break;
  670.     }
  671.  
  672.     // if we can’t find it, let the parent find it
  673.     if (result == nil)
  674.         result = MAppleObject::GetContainedObject(desiredType, keyForm, keyData, needDisposal);
  675.  
  676.     return result;
  677. }
  678.  
  679.  
  680. Boolean TESample::CompareAppleObjects(DescType operation, const MAppleObject& toWhat)
  681. {
  682.     return MAppleObject::CompareAppleObjects(operation, toWhat);
  683. }
  684.  
  685.  
  686. void TESample::DoFinderNew(const AppleEvent& message, AppleEvent& /* reply */)
  687. {
  688.     MAppleObject::GotRequiredParameters(message);
  689.     this->DoNew();
  690. }
  691.  
  692.  
  693. void TESample::DoFinderOpen(const AppleEvent& message, AppleEvent& /* reply */)
  694. {
  695.     AEDescList    listOfFiles;
  696.     OSErr        theErr;
  697.  
  698.     FailOSErr(AEGetParamDesc(&message, keyDirectObject, typeAEList, &listOfFiles));
  699.     TRY
  700.     {
  701.         long    numFiles;
  702.         FailOSErr(AECountItems(&listOfFiles, &numFiles));
  703.  
  704.         for (long i = 1; i <= numFiles; i++)
  705.         {
  706.             TRY
  707.             {
  708.                 DescType    actualType;
  709.                 FSSpec         theFileSpec;
  710.                 AEKeyword     theActualKey;
  711.                 Size        actualSize;
  712.                 FInfo        finderInfo;
  713.  
  714.                 FailOSErr(AEGetNthPtr(&listOfFiles, i, typeFSS, &theActualKey,
  715.                                       &actualType, (Ptr) &theFileSpec,
  716.                                       sizeof(theFileSpec), &actualSize));
  717.                 FailOSErr(FSpGetFInfo(&theFileSpec, &finderInfo));
  718.  
  719.                 MAppleObject::GotRequiredParameters(message);
  720.                 this->OpenADoc(theFileSpec.vRefNum, theFileSpec.parID, theFileSpec.name,
  721.                                finderInfo.fdType);
  722.             }
  723.             RECOVER
  724.             {
  725.                 goto processNextFile;
  726.             }
  727.             ENDTRY
  728.  
  729. processNextFile:
  730.             ;
  731.         }
  732.     }
  733.     RECOVER
  734.     {
  735.         theErr = AEDisposeDesc(&listOfFiles);
  736.     }
  737.     ENDTRY
  738.  
  739.     theErr = AEDisposeDesc(&listOfFiles);
  740. }
  741.  
  742.  
  743. void TESample::DoFinderPrint(const AppleEvent& /* message */, AppleEvent& /* reply */)
  744. {
  745.     // we don’t print from the finder, yet
  746. }
  747.  
  748.  
  749. void TESample::DoFinderQuit(const AppleEvent& message, AppleEvent& /* reply */)
  750. {
  751.     MAppleObject::GotRequiredParameters(message);
  752.     fDone = true;
  753. }
  754.  
  755.  
  756. MAppleObject* TESample::GetWindowObject(DescType form, const AEDesc& selectionData)
  757. {
  758.     WindowPtr    theWindow = nil;
  759.  
  760.     OSErr    ignoreErr;
  761.  
  762.     switch (form)
  763.     {
  764.     case formName:
  765.         {
  766.         AEDesc    theNameDesc;
  767.         Str255    theName;
  768.         Size    stringSize;
  769.         FailOSErr(AECoerceDesc(&selectionData, cText, &theNameDesc));
  770.         stringSize = GetHandleSize(theNameDesc.dataHandle);
  771.         if (stringSize < 256)
  772.         {
  773.             theName[0] = (char) stringSize;
  774.             BlockMove(*theNameDesc.dataHandle, &theName[1], stringSize);
  775.             theWindow = GetWindowFromName(theName);
  776.         }
  777.         ignoreErr = AEDisposeDesc(&theNameDesc);
  778.         }
  779.         break;
  780.     case formAbsolutePosition:
  781.         {
  782.         AEDesc    indexDesc;
  783.         short    index;
  784.         FailOSErr(AECoerceDesc(&selectionData, typeShortInteger, &indexDesc));
  785.         index = *(short*)*indexDesc.dataHandle;
  786.         ignoreErr = AEDisposeDesc(&indexDesc);
  787.  
  788.         theWindow = GetWindowFromIndex(index);
  789.         }
  790.         break;
  791.     default:
  792.         FailOSErr(errAEWrongDataType);
  793.     }
  794.  
  795.     return (TEDocument*) DocList()->FindDoc(theWindow);
  796. }
  797.  
  798.  
  799. void TESample::DoAppleNewElement(const AppleEvent& message, AppleEvent& /* reply */)
  800. {
  801.     DescType    returnedType;
  802.     DescType    classOfNewElement;
  803.     Size        actualSize;
  804.     FailOSErr(AEGetParamPtr(&message, keyAEObjToCreate, typeType, &returnedType,
  805.                             (Ptr) &classOfNewElement, sizeof(classOfNewElement),
  806.                             &actualSize));
  807.  
  808.     // we only create new windows
  809.     if (classOfNewElement != cWindow)
  810.         FailOSErr(errAEWrongDataType);
  811.  
  812.     MAppleObject::GotRequiredParameters(message);
  813.  
  814.     // create the new window
  815.     this->DoNew();
  816. }
  817.  
  818.  
  819. WindowPtr GetWindowFromName(Str255 name)
  820. {
  821.     WindowPtr    result = FrontWindow();
  822.     Str255        windowTitle;
  823.  
  824.     for (;result != nil;)
  825.     {
  826.         GetWTitle(result, windowTitle);
  827.         if (EqualString(windowTitle, name, false, true))
  828.             break;
  829.  
  830.         result = (WindowPtr) ((WindowPeek)result)->nextWindow;
  831.     }
  832.  
  833.     return result;
  834. }
  835.  
  836.  
  837. WindowPtr GetWindowFromIndex(short index)
  838. {
  839.     WindowPtr    result = FrontWindow();
  840.  
  841.     for (short i = 1; i < index  &&  result != nil; i++)
  842.         result = (WindowPtr) ((WindowPeek)result)->nextWindow;
  843.  
  844.     return result;
  845. }